
#include "Document.h"

#include "agg_scanline_u.h"
#include "agg_conv_curve.h"
#include "agg_renderer_scanline.h"
#include "agg_pixfmt_rgba.h"
typedef agg::pixfmt_bgra32 pixformat;

const double PI = 22.0/7.0;
const double PI2 = PI/2.0;

int Document::Create( int width, int height )
{
	_width = width; _height = height;

	// Create our bitmap
	BITMAPINFO binf = {0};
	binf.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	binf.bmiHeader.biWidth = width;
	binf.bmiHeader.biHeight = -height;
	binf.bmiHeader.biPlanes = 1;
	binf.bmiHeader.biBitCount = 32;
	binf.bmiHeader.biCompression = BI_RGB;
	binf.bmiHeader.biSizeImage = 0;
	void* pBmpBits = NULL;  // Will be freed by DeleteObject(hBmp)
	hBmp = CreateDIBSection( NULL, &binf, DIB_RGB_COLORS, &pBmpBits, NULL, 0 );
	if (!hBmp) {
		MessageBoxW( NULL, L"Error while create DIBSection", L"Draw", MB_OK|MB_ICONERROR );
		return 0;
	}
	aggbuf.attach((unsigned char*)pBmpBits, width, height, width * 4);

	pixformat pixf( aggbuf );
	pixf.attach( aggbuf );
	agg::renderer_base< pixformat > ren_base(pixf);
	ren_base.attach( pixf );
	ren_base.clear( agg::rgba8( 215, 235, 225 ) );
	
	bufDC = CreateCompatibleDC( NULL );
	SelectObject( bufDC, hBmp );

	/* test
	agg::scanline_u8 sl;
	agg::renderer_scanline_aa_solid< agg::renderer_base< pixformat > > ren_sl( ren_base );
	agg::path_storage path1, path2;
	path1.move_to( 100, 100 );
	path1.line_to( 120, 80 );
	path1.line_to( 140, 100 );
	path1.line_to( 120, 120 );
	path1.close_polygon();
	
	path2.move_to( 110, 100 );
	path2.line_to( 130, 80 );
	path2.line_to( 150, 100 );
	path2.line_to( 130, 120 );
	path2.close_polygon();

	agg::rasterizer_scanline_aa<> ras;
	agg::conv_smooth_poly1_curve<agg::path_storage> curve1( path1 );
	agg::conv_smooth_poly1_curve<agg::path_storage> curve2( path2 );
	ras.add_path( curve1 );
	//ras.add_path( curve2 );

	ren_sl.color( Color(12,34,65,20) );
	agg::render_scanlines( ras, sl, ren_sl );
	// test end
	*/
	// create temp buffer
	void* pBmpBits2 = NULL;  // Will be freed by DeleteObject(hBmp)
	hBmptemp = CreateDIBSection( NULL, &binf, DIB_RGB_COLORS, &pBmpBits2, NULL, 0 );
	if (!hBmptemp) {
		MessageBoxW( NULL, L"Error while create DIBSection", L"Draw", MB_OK|MB_ICONERROR );
		return 0;
	}
	aggbuftemp.attach((unsigned char*)pBmpBits2, width, height, width * 4);

	bufDCtemp = CreateCompatibleDC( NULL );
	SelectObject( bufDCtemp, hBmptemp );

	return 1;
}

Document::~Document(void)
{
	DeleteObject( hBmp );
	DeleteObject( hBmptemp );
	DeleteDC( bufDC );
	DeleteDC( bufDCtemp );
}

void Document::BeginStroke( double x, double y ) {
	tras.reset();
	pixformat pixf( aggbuftemp );
	agg::renderer_base< pixformat > ren_base( pixf );
	ren_base.copy_from( aggbuf );
	patht.remove_all();
	/*
	patha.remove_all();
	pathb.remove_all();

	patha.move_to( x, y );
	//pathb.move_to( x, y );

	*/
	stroke = STROKE_START;
}

void Document::EndStroke() {
	if( stroke == STROKE_NONE ) return;
	stroke = STROKE_NONE;
	/*

	pathb.invert_polygon( 0 );
	patha.join_path( pathb );
	patha.close_polygon();

	agg::rasterizer_scanline_aa<> ras;
	agg::conv_smooth_poly1_curve<agg::path_storage> curve( patha );
	//curve.smooth_value( 5 );
	ras.add_path( curve );
*/
	pixformat pixf( aggbuf );
	agg::renderer_base< pixformat > ren_base( pixf );
	agg::scanline_u8 sl;
	agg::renderer_scanline_aa_solid< agg::renderer_base< pixformat > > ren_sl( ren_base );

	ren_sl.color( penColor );

	agg::render_scanlines( tras, sl, ren_sl );
	
}

/*
////p1-------------p2
////|              |
////| width1       | width2
////|              |
////x1,y1--------x2,y2
////|              |
////|              |
////|              |
////p3-------------p4
*/
void Document::DrawLine( double x1, double y1, double x2, double y2, double width1, double width2 ) {
	double w12 = width1/2.0;
	double w22 = width2/2.0;

	stroke = STROKE_MIDDLE;

	pixformat pixf( aggbuftemp );
	agg::renderer_base< pixformat > ren_base( pixf );
	ren_base.copy_from( aggbuf );

	agg::scanline_u8 sl;
	agg::renderer_scanline_aa_solid< agg::renderer_base< pixformat > > ren_sl(ren_base);
	agg::path_storage path, pathc;

	double angle = atan2( y2-y1, x2-x1 );
	double p1x = x1 + w12 * cos( angle + PI2 );
	double p1y = y1 + w12 * sin( angle + PI2 );
	
	double p2x = x2 + w22 * cos( angle + PI2 );
	double p2y = y2 + w22 * sin( angle + PI2 );
	
	double p3x = x1 + w12 * cos( angle - PI2 );
	double p3y = y1 + w12 * sin( angle - PI2 );

	double p4x = x2 + w22 * cos( angle - PI2 );
	double p4y = y2 + w22 * sin( angle - PI2 );

	//patha.line_to( p1x, p1y );
	//patha.line_to( p2x, p2y );
	//patha.curve3( p1x, p1y, p2x, p2y );
	//pathb.line_to( p3x, p3y );
	//pathb.line_to( p4x, p4y );
	//pathb.curve3( p3x, p3y, p4x, p4y );

	path.move_to( p1x, p1y );
	path.line_to( p3x, p3y );
	path.line_to( p4x, p4y );
	path.line_to( p2x, p2y );
	path.close_polygon();
	tras.add_path( path );
	//patha.concat_path( path );
	//patha.concat_path( path );
	patht.concat_path( path );
	//patht.join_poly( path, 4, true );

	pathc.move_to( x2-w22, y2 );
	pathc.line_to( x2, y2-w22 );
	pathc.line_to( x2+w22, y2 );
	pathc.line_to( x2, y2+w22 );
	pathc.close_polygon();
	agg::conv_smooth_poly1_curve<agg::path_storage> curve( pathc );
	tras.add_path( curve );
	//patha.concat_path( curve );
	//patha.concat_path( curve );
	patht.concat_path( curve );
	//patht.join_path( curve );
	
	agg::rasterizer_scanline_aa<> ras;
	ras.add_path( patht );
	//ras.add_path( curve );
	//ras.add_path( pathc );

	ren_sl.color( penColor );
	agg::render_scanlines( ras, sl, ren_sl );
}
